package org.robot.scm.platform.server.handler;

import cn.hutool.core.codec.Base64Encoder;
import com.google.common.collect.Maps;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.StringTokenizer;
import org.apache.commons.lang3.StringUtils;
import org.robot.scm.platform.AbstractMonitor;
import org.robot.scm.pojos.config.BaseConfig;
import org.robot.scm.pojos.enums.PlatformEnum;

/**
 * @Author : Awn create on 2024/5/7 09:27
 */
public class BaseHandler {

    protected static final String SUCCESS = "{\"code\":0, \"ok\": true, \"msg\": \"%s\", \"data\": \"%s\"}";
    protected static final String FAILURE = "{\"code\":1, \"ok\": false, \"msg\": \"%s\", \"data\": \"%s\"}";

    public String getUri() {
        return StringUtils.EMPTY;
    }

    public boolean needAuth() {
        return Boolean.TRUE;
    }

    public BaseConfig config(PlatformEnum platformEnum) {
        return new BaseConfig(AbstractMonitor.mainConfig, AbstractMonitor.mainConfig.getPlatform(platformEnum));
    }

    protected void noCache(HttpExchange exchange) {
        exchange.getResponseHeaders().add("Cache-Control", "no-cache, no-store, must-revalidate");
        exchange.getResponseHeaders().add("Pragma", "no-cache");
        exchange.getResponseHeaders().add("Expires", "0");
    }

    protected void allowCors(HttpExchange exchange) throws IOException {
        // 设置允许跨域的响应头
        exchange.getResponseHeaders().add("Access-Control-Allow-Origin", "*");
        exchange.getResponseHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        exchange.getResponseHeaders().add("Access-Control-Allow-Headers", "Content-Type, Authorization");

        // 如果请求是预检请求（OPTIONS方法），则直接返回204状态码
        if ("OPTIONS".equals(exchange.getRequestMethod())) {
            exchange.sendResponseHeaders(204, 0);
            exchange.close();
        }
    }

    protected void sendSuccessResponse(HttpExchange exchange, String message, String data) throws IOException {
        String content = String.format(SUCCESS, message, Base64Encoder.encode(Objects.isNull(data) ? "" : data));
        exchange.getResponseHeaders().add("Content-Type", "text/plain; charset=UTF-8");
        try {
            exchange.sendResponseHeaders(200, content.getBytes(StandardCharsets.UTF_8).length);
        } catch (Exception ignored) {

        }
        try (OutputStream os = exchange.getResponseBody()) {
            os.write(content.getBytes(StandardCharsets.UTF_8));
        }
        exchange.close();
    }

    protected void sendSuccessResponse(HttpExchange exchange, String message) throws IOException {
        sendSuccessResponse(exchange, message, "");
    }

    protected void sendFailureResponse(HttpExchange exchange, String message, String data) {
        String content = String.format(FAILURE, message, Base64Encoder.encode(Objects.isNull(data) ? "" : data));
        exchange.getResponseHeaders().add("Content-Type", "text/plain; charset=UTF-8");
        try {
            exchange.sendResponseHeaders(200, content.getBytes(StandardCharsets.UTF_8).length);
        } catch (Exception ignored) {

        }
        try (OutputStream os = exchange.getResponseBody()) {
            os.write(content.getBytes(StandardCharsets.UTF_8));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        exchange.close();
    }

    protected void sendFailureResponse(HttpExchange exchange, String message) {
        sendFailureResponse(exchange, message, "");
    }

    protected static Map<String, String> queryToMap(String query) {
        if (StringUtils.isBlank(query)) {
            return Maps.newHashMap();
        }
        Map<String, String> queryPairs = new HashMap<>();
        StringTokenizer tokens = new StringTokenizer(query, "&");
        while (tokens.hasMoreTokens()) {
            String pair = tokens.nextToken();
            String[] keyValue = pair.split("=");
            String key = keyValue[0];
            String value = keyValue.length > 1 ? keyValue[1] : "";
            queryPairs.put(key, value);
        }
        return queryPairs;
    }

    public static boolean isSql(String input) {
        if (StringUtils.isBlank(input)) {
            return false;
        }
        String inputReg = input.replaceAll("\\s+", " ").trim().toLowerCase();
        return inputReg.startsWith("select")
                || inputReg.startsWith("insert")
                || inputReg.startsWith("update")
                || inputReg.startsWith("delete")
                || inputReg.startsWith("create")
                || inputReg.startsWith("truncate")
                || inputReg.startsWith("kill")
                || inputReg.startsWith("show")
                || inputReg.startsWith("alter")
                || inputReg.startsWith("drop")
                || inputReg.startsWith("use")
                || inputReg.startsWith("call")
                || inputReg.startsWith("desc")
                || inputReg.startsWith("describe")
                || inputReg.startsWith("grant")
                || inputReg.startsWith("revoke")
                || inputReg.startsWith("flush")
                || inputReg.startsWith("explain");
    }

    public static boolean likeSql(String input) {
        if (StringUtils.isBlank(input) || (StringUtils.contains(input, "权限") || StringUtils.contains(input, "开启") || StringUtils.contains(input, "关闭"))) {
            return false;
        }
        String inputReg = input.replaceAll("\\s+", " ").trim().toLowerCase();

        return inputReg.contains("select")
                || inputReg.contains("insert")
                || inputReg.contains("update")
                || (inputReg.contains("delete") && !inputReg.contains("deleted"))
                || (inputReg.contains("create") && !inputReg.contains("created"))
                || inputReg.contains("truncate")
                || inputReg.contains("kill")
                || inputReg.contains("show")
                || inputReg.contains("alter")
                || inputReg.contains("drop")
                || (inputReg.contains("use") && !inputReg.contains("user"))
                || inputReg.contains("call")
                || inputReg.contains("desc")
                || inputReg.contains("describe")
                || inputReg.contains("grant")
                || inputReg.contains("revoke")
                || inputReg.contains("flush")
                || inputReg.contains("explain");
    }
}
